/**********************************************************************************
// DemoAnima
// 
// Creation:	11 Jul 2007
// Updated:		27 May 2011
// Compiler:	Visual Studio 2010
//
// Notes:		Test the animation capabilities of the engine
//				Move and animate sprintes over a background image
//
**********************************************************************************/

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#include "Resources.h"
#include "Anabele.h"	

/**********************************************************************************/
/*                         AnimaDemo Class                                        */
/**********************************************************************************/

enum {STILL, WALKLEFT, WALKRIGHT, WALKUP, WALKDOWN};

class AnimaDemo: public D3DGame
{
private:
	Sprite * light;
	Sprite * background;
	Sprite * demobox;
	Sprite * demobar;
	Sprite * player;
	
	Animation * recovery;
	float lastx, lasty;
	float scaling;

	Animation * skyburst;
	Animation * lightning;

	Animation * left;
	Animation * right;
	Animation * up;
	Animation * down;
	Animation * upstill;
	Animation * downstill;
	
	int state;
	list<Animation *> expanim;
	list<Animation *>::iterator iexp;
	
	Input input;
	
	float directionX;
	char  text[80];

public:
	void GameInit();
	void GameLogic();
	void GameDraw();
	void GameShutDown();
	void LoadResources();
	void UnloadResources();
};

/**********************************************************************************/

void AnimaDemo::GameInit()
{
	input.Initialize();
	input.InitializeKeyboard();

	srand(GetTickCount());
	
	lastx = GetWindowWidth()/2.0f;
	lasty = GetWindowHeight()/2.0f;
	scaling = 1.0f;
	directionX = 3;	

	LoadResources();

	static uint leftSeq[] = {5,4,3,4};
	static uint rightSeq[] = {8,7,6,7};
	static uint downSeq[] = {0,2};
	static uint upSeq[] = {9,11};
	static uint downStillSeq[] = {1};
	static uint upStillSeq[] = {10};

	recovery = nullptr;
	skyburst = nullptr;
	
	left = new Animation(leftSeq, 4, 170, true);
	right = new Animation(rightSeq, 4, 170, true);
	down = new Animation(downSeq, 2, 170, true);
	up = new Animation(upSeq, 2, 170, true);
	upstill = new Animation(upStillSeq, 1, 0, true);
	downstill = new Animation(downStillSeq, 1, 0, true);
	player->animation = downstill;	

	static uint lightupSeq[] = {10,11,12,13,14,15,16,17,16,15,14,13,12,11};
	lightning = new Animation(lightupSeq, 14, 60, false, GetWindowWidth()/2.0f, GetWindowHeight()/2.0f);
	lightning->animMode = ENDLESS;
	light->animation = lightning;
}

/**********************************************************************************/

void AnimaDemo::LoadResources()
{
	// load sprites and set recovery parameters

	background = new Sprite("Resources/backg.png");
	background->MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()/2.0f);
	background->Scale(GetWindowWidth()/float(background->GetWidth()), GetWindowHeight()/float(background->GetHeight()));

	demobox = new Sprite("Resources/demoBox.png");
	demobox->MoveTo(150, 100);
	
	demobar = new Sprite("Resources/demoBar.png");
	demobar->MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()-30.0f);

	light = new Sprite("Resources/lights.png", 192, 192, 5);
	light->scalingX = scaling * 3.0f;
	light->scalingY = scaling * 3.0f;

	player = new Sprite("Resources/naruto.png", 90, 128, 3);
	player->animation = recovery;
	player->MoveTo(lastx, lasty);
	player->scalingX = scaling;
	player->scalingY = scaling;
}

/**********************************************************************************/

void AnimaDemo::UnloadResources()
{
	recovery = player->animation;
	lastx = player->x;
	lasty = player->y;
	scaling = player->scalingX;

	// delete sprites
	if (player) delete player;
	if (light) delete light;
	if (demobar) delete demobar;
	if (demobox) delete demobox;
	if (background) delete background;
}


/**********************************************************************************/

void AnimaDemo::GameShutDown()
{
	// delete explosion animations left
	for (iexp = expanim.begin(); iexp != expanim.end(); ++iexp)
		delete *iexp;
	expanim.clear();

	// delete animations
	if (left) delete left;
	if (right) delete right;
	if (up) delete up;
	if (down) delete down;

	UnloadResources();
}

/**********************************************************************************/

void AnimaDemo::GameLogic()
{
	// for now test if user is hitting ESC and quit game
	EndsOnEscape();

	input.GetKeyboardState();

	// Fire (Space Bar)
	if (input.KeyPressed(DIK_SPACE))
	{
		float xExp = float(rand() % (GetWindowWidth()-(light->GetWidth()/2)));
		float yExp = float(rand() % (GetWindowHeight()-(light->GetWidth()/2)));
		
		skyburst = new Animation(nullptr, 25, 33, false, xExp, yExp);
		expanim.push_back(skyburst);
	}

	if (player->animation && !player->animation->Active())
	{
		// Move Left
		if (input.KeyPressed(DIK_LEFT))
		{
			state = WALKLEFT;
			player->x -= directionX;
			player->animation = left;
			left->Restart();
		} 
		else 
		// Move Right
		if (input.KeyPressed(DIK_RIGHT))
		{
			state = WALKRIGHT;
			player->x += directionX;
			player->animation = right;
			right->Restart();
		}
		else 
		// Move Up
		if (input.KeyPressed(DIK_UP))
		{
			state = WALKUP;
			player->Scale(0.83f, 0.83f);
			light->Scale(0.83f, 0.83f);
			player->animation = up;
			up->Restart();
		}
		else 
		// Move Down
		if (input.KeyPressed(DIK_DOWN))
		{
			state = WALKDOWN;
			player->Scale(1.2f, 1.2f);
			light->Scale(1.2f, 1.2f);
			player->animation = down;
			down->Restart();
		}
		else
		{
			if (state == WALKUP)
			{
				state = STILL;
				player->animation = upstill;
			} 
			else if (state == WALKDOWN)
			{
				state = STILL;
				player->animation = downstill;
			}
		}
	}
	else
	{
		switch (state)
		{
		case WALKLEFT: 
			player->x -= directionX;
			break;
		case WALKRIGHT:
			player->x += directionX;
			break;
		}

		player->animation->NextFrame();
	}
} 

/**********************************************************************************/

void AnimaDemo::GameDraw()
{	
	iexp = expanim.begin();
	while (iexp != expanim.end())
	{
		if ((*iexp)->Active())
		{
			(*iexp)->NextFrame();
			light->animation = (*iexp);
			light->Draw();
			++iexp;
		}
		else
		{
			// clean explosion
			delete *iexp;
			iexp = expanim.erase(iexp);
		}
	}
	
	light->animation = lightning;
	light->animation->NextFrame();
	light->Draw();
	
	player->Draw();	

	background->Draw();
	demobox->Draw();
	demobar->Draw();

	sprintf_s(text, "Animation Demo");
	sysFont->Draw(55, 40, text);

	sprintf_s(text, "Sprite sheet animation");
	sysFont->Draw(55, 75, text);

	sprintf_s(text, "Matrix scaling and translation");
	sysFont->Draw(55, 95, text);

	sprintf_s(text, "Image position: %d x %d", player->IntX(), player->IntY());
	sysFont->Draw(55, 115, text);

	sprintf_s(text, "Image scaling: %.1f x", player->scalingX);
	sysFont->Draw(55, 135, text);

	sprintf_s(text, "Use <ARROWS> to move and <SPACE> for lightning");
	sysFont->Draw(0, GetWindowHeight()-37, text, Color(255,255,255), GetWindowWidth(), 30, DT_CENTER);
}

/**********************************************************************************/
/*                                  WinMain                                       */
/**********************************************************************************/

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AnimaDemo animDemo;

	//animDemo.SetWindowMode(WINDOWED);
	//animDemo.SetWindowSize(1024,768);	
	animDemo.SetWindowBgColor(16,16,16);
	animDemo.SetWindowTitle(string("Anima Demo"));
	animDemo.SetWindowIcon(LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)));
	animDemo.SetWindowCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDI_CURSOR)));
	animDemo.ShowWindowCursor(false);
	animDemo.Initialize(hInstance);
	animDemo.Start();
	
	return 0;
}

/**********************************************************************************/

